package com.yonyou.ucf.mdd.query.impl;

import com.yonyou.cloud.bean.GroupInfo;
import com.yonyou.cloud.common.IConfigKey;
import com.yonyou.cloud.middleware.MiddlewareRuntimeEnvironment;
import com.yonyou.cloud.util.IrisDynamicInvokeUtil;
import com.yonyou.diwork.service.auth.IDiWorkPermissionService;
import com.yonyou.iuap.graphql.model.IQuerySchema;
import com.yonyou.iuap.graphql.query.IGraphQLQueryApi;
import com.yonyou.iuap.graphql.query.IGraphQLQueryResultProcessor;
import com.yonyou.iuap.yms.config.utils.YmsPropertyUtil;
import com.yonyou.ucf.mdd.api.interfaces.rpc.IComQueryApi;
import com.yonyou.ucf.mdd.ext.dubbo.DubboReferenceUtils;
import org.apache.commons.lang3.StringUtils;
import org.imeta.biz.base.BizContext;
import org.imeta.core.lang.BooleanUtils;
import org.imeta.core.model.Entity;
import org.imeta.core.model.EntityProfile;
import org.imeta.core.model.MetaProfileManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MddGraphQLQueryImpl implements IGraphQLQueryApi {

    @Autowired(required = false)
    private IComQueryApi comQueryApi;

    @Autowired
    private YmsPropertyUtil propertyUtil;

    @Override
    public <T> List<T> queryForList(IQuerySchema querySchema, IGraphQLQueryResultProcessor resultProcessor) {
        String fullname = querySchema.from().fullname();
        Entity entity = BizContext.getMetaRepository().entity(fullname);
        Assert.notNull(entity,()->String.format("can't find entity by fullname : %s",fullname));

        // 判断是否ES查询
        boolean ESQuery = "es".equalsIgnoreCase(entity.service());

        String domain = entity.domain();
        IComQueryApi comQueryApi = null;
        // ES || domain为空 || 当前domain
        if(ESQuery || isSelfDomain(domain)) {
            Assert.notNull(this.comQueryApi,()->String.format("Entity : %s ,domain : %s , useEs : %s , IComQueryApi is null",fullname,domain,ESQuery));
            comQueryApi = this.comQueryApi;
        }
        // 配置了查询仓的也走本地查询
        else if (this.comQueryApi != null && isSupportNativeQuery(domain)) {
            comQueryApi = this.comQueryApi;
        }
        // 执行远程RPC
        else {
            // PROVIDER_ID 目前能提供comQueryAPI的都是MDD/YPD框架，providerId指定为C87
//            comQueryApi = IrisDynamicInvokeUtil.getService(domain, IConfigKey.Keys.PROVIDER_ID.getDefaultValue(),"",IComQueryApi.class);
            comQueryApi = DubboReferenceUtils.getDubboService(IComQueryApi.class, domain, null);
        }

        List<Map<String,Object>> results = null;
        try {
            results = comQueryApi.query(fullname,querySchema.toString(),ESQuery);
        } catch (Exception e) {
            if(e instanceof RuntimeException) {
                throw (RuntimeException)e;
            }
            throw new RuntimeException(e);
        }
        return results.stream().map(result -> (T)result).collect(Collectors.toList());
    }

    private boolean isSelfDomain(String domain) {
        boolean isSelfDomain = true;
        if (StringUtils.isNotBlank(domain)) {
            String currentDomain = MiddlewareRuntimeEnvironment.get(IConfigKey.Keys.APP_CODE);
            String parentDomain = GroupInfo.getGroup(domain, MiddlewareRuntimeEnvironment.get(IConfigKey.Keys.PROVIDER_ID));
            isSelfDomain = currentDomain == null || currentDomain.equalsIgnoreCase(domain) || currentDomain.equalsIgnoreCase(parentDomain);
        }
        return isSelfDomain;
    }

    /**
     * 走IMeta判断是否可以走本域查询
     * @param domain
     * @return
     */
    private boolean isSupportNativeQuery(String domain) {
        boolean enableNativeQuery = BooleanUtils.b( propertyUtil.getProperty("mdd.query.enableNativeQuery",false), true);
        MetaProfileManager profileManager = MetaProfileManager.getInstance();
        EntityProfile entityProfile = profileManager.getEntityProfile();
        String parentDomain = GroupInfo.getGroup(domain, MiddlewareRuntimeEnvironment.get(IConfigKey.Keys.PROVIDER_ID));

        return enableNativeQuery && entityProfile != null
                && entityProfile.getDomainDatabases() != null
                && (entityProfile.getDomainDatabases().containsKey(domain)
                || entityProfile.getDomainDatabases().containsKey(parentDomain)
        );
    }
}
